// Copyright 2012 Square, Inc.
package com.squareup.timessquare;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.app.Context;

/**
 * ViewGroup that draws a grid of calendar cells.  All children must be {@link CalendarRowView}s.
 * The first row is assumed to be a header and no divider is drawn above it.
 */
public class CalendarGridView extends ComponentContainer implements Component.LayoutRefreshedListener {
    /**
     * The grid lines don't exactly line up on certain devices (Nexus 7, Nexus 5). Fudging the
     * co-ordinates by half a point seems to fix this without breaking other devices.
     */
    private static final float FLOAT_FUDGE = 0.5f;

    private final Paint dividerPaint = new Paint();
    private int oldWidthMeasureSize;
    private int oldNumRows;

    public CalendarGridView(Context context, AttrSet attrs) {
        super(context, attrs);
        dividerPaint.setColor(Color.BLUE);
        setLayoutRefreshedListener(this);
    }

    /**
     * setDividerColor
     * @param color color
     */
    public void setDividerColor(int color) {
        dividerPaint.setColor(new Color(color));
    }

    /**
     * setDayViewAdapter
     * @param adapter adapter
     */
    public void setDayViewAdapter(DayViewAdapter adapter) {
        for (int i = 0; i < getChildCount(); i++) {
            ((CalendarRowView) getComponentAt(i)).setDayViewAdapter(adapter);
        }
    }

    /**
     * setDayBackground
     * @param resId resId
     */
    public void setDayBackground(int resId) {
        for (int i = 1; i < getChildCount(); i++) {
            ((CalendarRowView) getComponentAt(i)).setCellBackground(resId);
        }
    }

    /**
     * setDayTextColor
     * @param resId resId
     */
    public void setDayTextColor(int resId) {
    }

    /**
     * setDisplayHeader
     * @param displayHeader displayHeader
     */
    public void setDisplayHeader(boolean displayHeader) {
        getComponentAt(0).setVisibility(displayHeader ? VISIBLE : HIDE);
    }

    /**
     * setHeaderTextColor
     * @param color color
     */
    public void setHeaderTextColor(int color) {
        ((CalendarRowView) getComponentAt(0)).setCellTextColor(color);
    }

    /**
     * setTypeface
     * @param typeface typeface
     */
    public void setTypeface(Font typeface) {
        for (int i = 0; i < getChildCount(); i++) {
            ((CalendarRowView) getComponentAt(i)).setTypeface(typeface);
        }
    }

    @Override
    public void addComponent(Component child, int index, LayoutConfig params) {
        if (getChildCount() == 0) {
            ((CalendarRowView) child).setIsHeaderRow(true);
        }
        super.addComponent(child, index, params);
    }

    /**
     * dispatchDraw
     * @param canvas canvas
     */
    protected void dispatchDraw(Canvas canvas) {
        final ComponentContainer row = (ComponentContainer) getComponentAt(1);
        int top = row.getTop();
        int bottom = getBottom();
        // Left side border.
        final int left = row.getComponentAt(0).getLeft() + getLeft();
        canvas.drawLine(new Point(left + FLOAT_FUDGE, top), new Point(left + FLOAT_FUDGE, bottom), dividerPaint);

        // Each cell's right-side border.
        RgbColor color = new RgbColor();
        for (int c = 0; c < 7; c++) {
            float x1 = left + row.getComponentAt(c).getRight() - FLOAT_FUDGE;
            canvas.drawLine(new Point(x1, top), new Point(x1, bottom), dividerPaint);
        }
    }

    /**
     * drawChild
     * @param canvas canvas
     * @param child child
     * @param drawingTime drawingTime
     * @return boolean
     */
    protected boolean drawChild(Canvas canvas, Component child, long drawingTime) {
        // Draw a bottom border.
        final int bottom = child.getBottom() - 1;
        canvas.drawLine(new Point(child.getLeft(), bottom), new Point(child.getRight() - 2, bottom), dividerPaint);
        return true;
    }

    /**
     * onMeasure 无法使用
     * @param widthMeasureSpec widthMeasureSpec
     * @param heightMeasureSpec heightMeasureSpec
     */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMeasureSize = MeasureSpec.getSize(widthMeasureSpec);
        if (oldWidthMeasureSize == widthMeasureSize) {
            Logr.debug("SKIP Grid.onMeasure");
            return;
        }
        long start = System.currentTimeMillis();
        oldWidthMeasureSize = widthMeasureSize;
        int cellSize = widthMeasureSize / 7;
        // Remove any extra pixels since /7 is unlikely to give whole nums.
        widthMeasureSize = cellSize * 7;
        int totalHeight = 0;
        for (int c = 0, numChildren = getChildCount(); c < numChildren; c++) {
            final Component child = getComponentAt(c);
            child.setMinHeight(cellSize);
            if (child.getVisibility() == Component.VISIBLE) {
                totalHeight += child.getHeight();
            }
        }
        final int measuredWidth = widthMeasureSize + 2; // Fudge factor to make the borders show up.
        Logr.debug("Grid.onMeasure %d ms", System.currentTimeMillis() - start);
    }

    @Override
    public void onRefreshed(Component component) {
        int left = component.getLeft();
        int top = 0;
        int right = component.getRight();
        int bottom = component.getBottom();
        for (int i = 0, numChildren = getChildCount(); i < numChildren; i++) {
            final Component child = getComponentAt(i);
            final int rowHeight = child.getHeight();
            child.setLeft(left);
            child.setTop(top);
            child.setRight(right);
            child.setBottom(top + rowHeight);
            top += rowHeight;
        }
    }

    /**
     * setNumRows
     * @param numRows numRows
     */
    public void setNumRows(int numRows) {
        if (oldNumRows != numRows) {
            // If the number of rows changes, make sure we do a re-measure next time around.
            oldWidthMeasureSize = 0;
        }
        oldNumRows = numRows;
    }
}
